home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 6 / MacMania 6.toast / / Tools&Utilities / EnterAct Stuff / Documentation / hAWK_notes.h < prev    next >
Text File  |  1992-11-22  |  45KB  |  940 lines

  1. /* Add this file to an EnterAct project (and update the dictionary)
  2. for a bit of help with hAWK programming.
  3. */
  4. /* This help is general, and defines the following terms:
  5. term            what’s in the note
  6. ----            --------------------
  7. variables        hAWK’s built–in variables
  8. array            general discussion
  9. in                the “in” operator
  10. BEGIN            about BEGIN blocks
  11. END                ditto END blocks
  12. regular            a discussion of regular expressions,
  13.                     with examples
  14. patterns        general discussion
  15. operators        table, precedence and definition
  16. numeric         (functions) table
  17. string             (functions) table
  18. control            for while do etc
  19. function        how to define one, etc
  20. print            
  21. printf
  22. redirect        redirecting input and output
  23.  
  24. To look up one of the above defined terms, type its name (or click at the end
  25. of the name) and press the <Enter> key. If you have the AutoLook window open,
  26. the definition will appear there if you type the name or double–click
  27. on it (or click at the end of it, or paste it...)
  28. */
  29. struct variables
  30.     {/*
  31.     Built–in variables
  32. hAWK's built-in variables are:
  33. ARGC            the number of input files plus one
  34. ARGV            array of command line arguments. The array is indexed from
  35.                 0 to ARGC - 1, the input file names being ARGV[1] through
  36.                 ARGV[ARGC-1]. Dynamically changing the contents of ARGV
  37.                 can control the files used for data.
  38. FILENAME        the name of the current input file. If no files are
  39.                 specified on the command line, the value of FILENAME is
  40.                 "-". A hAWK program may do all of its work in a BEGIN
  41.                 block, with no need for input (generating a list of random
  42.                 numbers for example).
  43. FNR                the input record number in the current input file. Reset
  44.                 to 1 when starting a new input file. Hence the pattern
  45.                 “FNR == 1” detects the start of each file.
  46. FS                the input field separator, a blank by default. If the
  47.                 default FS is used then leading blanks and tabs are
  48.                 trimmed from $1.
  49. IGNORECASE        controls the case-sensitivity of all regular expression
  50.                 operations. If IGNORECASE has a non-zero value, then
  51.                 pattern matching in rules, field splitting with FS ,
  52.                 regular expression matching with ~ and !~ , and the gsub()
  53.                 , index() , match() , split() , and sub() pre-defined
  54.                 functions will all ignore case when doing regular
  55.                 expression operations. Thus, if IGNORECASE is not equal to
  56.                 zero, /aB/ matches all of the strings "ab", "aB", "Ab",
  57.                 and "AB". The initial value of IGNORECASE is zero, so all
  58.                 regular expression operations are normally case-sensitive.
  59. NF                the number of fields in the current input record.
  60. NR                the total number of input records seen so far.
  61. OFMT            the output format for numbers, %.6g by default.
  62. OFS                the output field separator, a blank by default.
  63. ORS                the output record separator, by default a newline.
  64. RS                the input record separator, by default a newline. RS is
  65.                 exceptional in that only the first character of its string
  66.                 value is used for separating records. If RS is set to the
  67.                 null string, then records are separated by blank lines.
  68.                 When RS is set to the null string, then the newline
  69.                 character always acts as a field separator, in addition to
  70.                 whatever value FS may have.
  71. RSTART            the index of the first character matched by match(); 0 if no match.
  72. RLENGTH            the length of the string matched by match(); -1 if no match.
  73. SUBSEP            the character used to separate multiple subscripts in array
  74.                 elements, by default "\034", some kinda up arrow very rare in text.
  75. (and three added for the Macintosh version)
  76. RUNERR            short for "run error", a file name that you can use to print
  77.                 your own error messages to, as in 
  78.                     print "Error during run" > RUNERR.
  79.                 Default name is $tempRunErr, and you'll find the file
  80.                 in the same folder as $tempStdOut.
  81. STDPATH            path name that can be prefixed to any file name you wish to be
  82.                 written to the same folder as stdout ($tempStdOut). Typically
  83.                 looks like
  84.                     "Disk:folder1...:folderN:" and typical use looks like
  85.                     outname = "MyOutFile"
  86.                     fullOutName = STDPATH outname;
  87.                     print "something" > fullOutName;
  88. TIME            at start of run, eg "Sunday, October 13, 1991 07:58 AM"
  89.     */};
  90.  
  91. struct array
  92.     {/*
  93. Arrays are subscripted with an expression between square brackets,
  94. arr"["expr"]". Array values can be numbers or strings, but the index is
  95. always interpreted as a string. For example, when you write
  96.     arr[1]
  97. the 1 is converted to the string "1" for use as the array index, so arr[1]
  98. is the same as arr["1"]. This sort of array is called “associative” since
  99. it can associate one string of text with any other, eg
  100.         arr["John Henry"] = "was a log-drivin man"
  101.  
  102. If the index expression is an expression list ( expr1 ", " expr " ...)"
  103. then the array subscript is a string consisting of the concatenation of
  104. the (string) value of each expression, separated by the value of the
  105. SUBSEP variable, which is by default “\034” (decimal 28, an up arrow).
  106. This facility is used to simulate multiply–dimensioned arrays. For
  107. example:
  108.     i = "A" ; j = "B" ;k = "C"
  109.     x[i, j, k] = "hello, world"
  110. assigns the string "hello, world" to the element of the array x
  111. which is indexed by the string "A\034B\034C".
  112.     */};
  113.  
  114. struct in
  115.     {/*
  116. The special operator "in" may be used in an if statement to see if an
  117. array has an index consisting of a particular value:
  118.     if (val in array)
  119.         print array[val]
  120. If the array has multiple subscripts i j k, use
  121. if ((i, j,k) in array) instead . The alternate
  122.     if (array[val] != "")
  123. actually creates the array array[val] element if it does not exist, so
  124. using “in” is usually better.
  125.  
  126. The "in" construct may also be used in a for loop to iterate over all the
  127. elements of an array:
  128.     for (i in arr)
  129.         delete arr[i]
  130. An element may be deleted from an array using the delete statement. New
  131. elements should not be added to an array while looping over it with the
  132. "in" for-loop, since hAWK isn’t quite smart enough to handle that very
  133. well.
  134.     */};
  135.  
  136. struct BEGIN
  137.     {/*
  138. BEGIN and END are two special kinds of patterns which are not tested
  139. against the input. The action parts of all BEGIN patterns are merged as if
  140. all the statements had been written in a single BEGIN block. They are
  141. executed before any of the input is read. Similarly, all the END blocks
  142. are merged, and executed when all the input is exhausted (or when an exit
  143. statement is executed). BEGIN and END patterns cannot be combined with
  144. other patterns in pattern expressions. BEGIN and END patterns cannot have
  145. missing action parts.
  146.  
  147.     BEGIN {FS = ",[ \t]*|[ \t]+"}
  148. sets the field separator to either a comma followed by optional blanks and
  149. tabs or one or more blanks and tabs—a common field separator in a real
  150. database.
  151.  
  152. END blocks are often used to finish up after all the input has been seen,
  153. as in this little program:
  154.             {out[++n] = $0}
  155.     END {for (i = n; i >= 1; --i) print out[i]}
  156. which accumulates all input records in the array “out”, and then at the
  157. end prints out the records in reverse order.
  158.     */};
  159.  
  160. struct END
  161.     {/*
  162. BEGIN and END are two special kinds of patterns which are not tested
  163. against the input. The action parts of all BEGIN patterns are merged as if
  164. all the statements had been written in a single BEGIN block. They are
  165. executed before any of the input is read. Similarly, all the END blocks
  166. are merged, and executed when all the input is exhausted (or when an exit
  167. statement is executed). BEGIN and END patterns cannot be combined with
  168. other patterns in pattern expressions. BEGIN and END patterns cannot have
  169. missing action parts.
  170.  
  171.     BEGIN {FS = ",[ \t]*|[ \t]+"}
  172. sets the field separator to either a comma followed by optional blanks and
  173. tabs or one or more blanks and tabs—a common field separator in a real
  174. database.
  175.  
  176. END blocks are often used to finish up after all the input has been seen,
  177. as in this little program:
  178.             {out[++n] = $0}
  179.     END {for (i = n; i >= 1; --i) print out[i]}
  180. which accumulates all input records in the array “out”, and then at the
  181. end prints out the records in reverse order.
  182.     */};
  183.  
  184. struct regular /*expression */
  185.     {/*
  186. A regular expression is nothing more than a string of text with optional
  187. special “metacharacters”, and in most cases the string to be used can
  188. result from the evaluation of a variable, or the concatenation of several
  189. strings or variables. This means you can build the regular expressions for
  190. your program during the execution of your program, modifying them on the
  191. fly to suit changing circumstances.
  192.  
  193. Parts of a regular expression can be grouped (with ordinary parentheses),
  194. and later in the regular expression or in a replacement string can be
  195. referred to by the group “tags” \1, \2, ... \9 where \1 refers to the
  196. group started by the first left parenthesis, \2 to the second, etc. These
  197. allow you to match a small pattern within the context of a larger one,
  198. detect duplicate expressions, change the order of the groups and so on.
  199. Note that parentheses have the highest precedence of all regular
  200. expression “operators”, so they serve two purposes; changing the order in
  201. which the metacharacters apply, and marking the boundaries of a group, for
  202. later reference via \1..\9. More on this in a bit.
  203.  
  204. Regular expressions are built from ordinary characters, the escape
  205. sequences
  206.     \t  \n  \b  \B  \w  \W  \<  \>  \1  \2  \3  \4  \5  \6  \7  \8  \9
  207. and from the metacharacters
  208.             \ ^ $ . [ ] | ( ) * + ?
  209. which are the ones with the special powers mentioned above. As you saw in
  210. the above section, if a regular expression contains no metacharacters then
  211. it behaves like an ordinary “find” string in that each character in the
  212. regular expression must match a character in the string being searched.
  213. The following table summarizes all character usage in a regular expression
  214. (where a b c are ordinary characters, m is a metacharacter, r is a regular
  215. expression, and d is a digit):
  216.  
  217. c            matches the non-metacharacter c itself
  218. \m            matches the literal character m, eg \$ matches the dollar sign.
  219. .            matches any single character except newline.
  220. ^            matches the beginning of a line or a string.
  221. $            matches the end of a line or a string.
  222. [ abc... ]    character class, matches any one of the characters    a or b or c etc... .
  223. [^ abc... ]    negated character class, matches any character except abc...
  224.             and newline. (Ranges of characters may be abbreviated in
  225.             character classes, as in [0-9] which matches any digit,
  226.             [A-Za-z] which matches any letter, [^0-9] which matches
  227.             anything but a digit)
  228. \w            matches a “word” character, exactly equivalent to [0-9A-Za-z_]
  229. \W            matches a non-word character, ie [^0-9A-Za-z_]
  230. \<            matches the beginning of a word.
  231. \>            matches the end of a word.
  232. \b            matches the beginning or end of a word (a word boundary).
  233. \B            matches the boundary (beginning or end) of a set
  234.             of non-word characters.
  235. \t            matches a tab.
  236. \n            matches a newline (the Return key).
  237. r1 | r2        alternation: matches either r1 or r2, eg "blue|green"
  238. r1r2        concatenation: matches r1 followed by r2 .
  239. r +            matches one or more r 's. 
  240. r *            matches zero or more r 's.  (Note that zero r’s can
  241.             be anywhere in the text)
  242. r ?            matches zero or one r 's. 
  243. ( r )        grouping: matches r. Parentheses have two distinct uses;
  244.             to override default precedence of metacharacter operators, and
  245.             to tag a subexpression for subsequent reference.
  246. \1...\9        stand for whatever text the first through ninth set of
  247.             parentheses currently match, counting opening parentheses from
  248.             left to right. Note that if the pair of parentheses has a + or
  249.             * or ? operator after it, then all of the matches are
  250.             included, eg /(foo)+bar/ applied to "foofoofoobar" will set \1
  251.             to "foofoofoo". To get just the first foo, use /(foo)\1*bar/ -
  252.             then \1 is set to "foo". (Perl users note this is the opposite
  253.             of what you are used to).
  254. \ddd        is interpreted as an octal number, as in C. The digits
  255.             exclude 8 and 9, needless to say, and there can be from 1 to 3
  256.             digits in the number. Note that \1 through \7 are interpreted
  257.             as subexpression tags unless followed immediately by another
  258.             octal digit (eg \23 is not tag 2 followed by a 3, it is the
  259.             octal number 19 decimal). \8 and \9 are always tags, since 8
  260.             and 9 are not octal numbers. To refer to octal numbers 1 to 7,
  261.             use \01 to \07. To follow a tag with a low number (eg \2
  262.             followed by 3), use the octal representation of the number (eg
  263.             \2\063 -- \063 equals 51 decimal, the ASCII code for 3).
  264.  
  265. The metacharacters ^ and $ to match the beginning and end of strings, and
  266. \b \B \< \> to match various boundaries don’t actually match any
  267. characters; rather they force alignment to a particular text position. For
  268. example, /\brun\b/ will always match just “run” if it matches anything,
  269. but will not match "runner" or "brunt". By comparison, /\Wrun\W/ won’t
  270. match “runner” or “brunt” either, but it will include any non–word
  271. character that happens to come before or after the word “run”. Normally
  272. you won’t want to include leading or trailing spaces etc in the match.
  273.  
  274. Parentheses () have the highest precedence, allowing you to override
  275. default precedence when needed. The “repetition” operators * + ? have the
  276. next–highest precedence, followed by concatenation, with alternation
  277. having the lowest precedence of all. For example, in abc*d the * applies
  278. only to the c since the repetition operator acts before concatenation, and
  279. in abd|def the | applies to abd and def since concatenation binds them
  280. together into little groups of three before alternation can play.
  281.  
  282. Regular expression can be used to just locate an instance of a
  283. pattern, as in
  284.     $0 ~ /extern/
  285. but they can also be used to specify text for replacement, by using the
  286. “sub” and “gsub” functions. Looking ahead just a bit, these functions take
  287. a regular expression as the first argument, the string to use for
  288. replacement as the second argument, and the string to do the search and
  289. replace in as the third argument, with $0 used by default if there is no
  290. third argument. “sub” does a single substitution on the text, and “gsub”
  291. does all possible non-overlapping substitutions. Within the replacement
  292. strings of these functions, you can use \1 through \9 to refer to text
  293. currently matched by tagged subexpressions, and the ampersand “&” stands
  294. for all of the text that was matched. To put a plain ampersand in the
  295. replacement, use “\&”.
  296.  
  297. At this point some considerable exampling usually helps:
  298. The quick brown            matches just that, "The quick brown". Note it
  299.                         would match "The quick brown" in "The quick brownie".
  300. red fox\.                matches "red fox." (the period must be
  301.                         escaped for a literal match).
  302. [ \t]                    matches a single space or tab
  303.                         (that’s a space before the \).
  304. [ \t]+                    matches any consecutive run of spaces and tabs
  305.                         in any mix.
  306. [0-9]+                    matches an integer (read “one or more digits”)
  307. [+-]?[0-9]+                matches an integer, together with any preceding sign.
  308. [A-Za-z]+                matches an English word (unhyphenated).
  309. houses?                    matches "house" or "houses".
  310. m(iss)*ippi                matches "mippi", "missippi", "mississippi",
  311.                         "missississippi", etc.
  312. ar*g                    matches "ag", "arg", "arrg", "arrrg", etc.
  313. MyFunction\(            matches "MyFunction(".
  314. array\[index\]            matches "array[index]".
  315. array\[.+\]                matches "array[i]", "array[j]", "array[2*q-1]", etc.
  316. \\([0-7]|[0-7][0-7])    matches "\d" or "\dd" where d is an octal digit.
  317. ([^\\]?|(\\\\)+)"        (horrors, be brave) matches an unescaped quote or
  318.                         a quote preceded by an even number of
  319.                         backslashes—in other words a true quote in C. The
  320.                         backslash is a metacharacter, so matching one
  321.                         literally requires a backslash before the
  322.                         backslash.
  323. The[ \t]+quick[ \t]+brown    matches "The quick brown" with variable
  324.                             spaces and tabs between the words.
  325. \/\*                    matches the start of a C comment, "/ *". The
  326.                         forward slash is escaped so that you can place the
  327.                         whole regular expression inside forward slashes.
  328.                         The escape before '/' would not be needed if you
  329.                         placed the expression inside quotes, but then you
  330.                         would need two escapes before the '*', ie "/\\*".
  331. \/\*.*\*\/                matches all of a one–line C comment,
  332.                         "/ * - anything - * /".
  333. ^Z                        matches a 'Z' at the beginning of a string.
  334. ^.                        matches the first character of a string.
  335. .$                        matches the last character of a string.
  336. ^.*$                    matches any string completely (and is therefore useless).
  337. ^A..$                    matches any string which is three characters long,
  338.                         the first being an 'A'.
  339. ^(A|B).*                matches all of any string that begins with 'A' or 'B'.
  340. ^[AB].*                    does likewise.
  341. \w+                        matches a C term, or integer constant.
  342. ((->)|(\.))(mem\b)        matches “mem” when it is immediately preceded by “->”
  343.                         or “.”, and is not the beginning of a longer word.
  344.                         For replacement purposes in a “sub” or “gsub”, the
  345.                         part before “mem” is given by \1, and mem itself
  346.                         is \4.
  347. gsub(/((->)|(\.))(mem\b)/, "\1\4ber") will turn “->mem” into “->member”
  348.                         and “.mem” into “.member” everywhere in the
  349.                         current input line $0, ignoring things like
  350.                         “remember” or “->memories”.
  351. gsub(/\bFuncName([ \t]*\()/, "FunctionName\1") will replace “FuncName” by
  352.                         “FunctionName” everywhere in the current input
  353.                         line $0, provided it is followed on the same line
  354.                         by an opening parenthesis, with optional spaces or
  355.                         tabs between the name and “(”. The match extends
  356.                         from the “F” of “FuncName” up to and including the
  357.                         “(”, so the “(” and any intervening white space
  358.                         must be put back into the replacement string by
  359.                         tagging them in parentheses and using \1 after
  360.                         “FuncName” to refer to what was matched by the
  361.                         first set of parentheses in the pattern.
  362.  
  363.  
  364. Within a character class most metacharacters are taken literally. The
  365. exceptions are the escaping backslash \, the negating ^ (only at the
  366. beginning), and the range hyphen - (only between two characters). For
  367. example,
  368.         [A-Za-z-]        matches an English word, hyphens included
  369.         [-A-Za-z]        does the same
  370.         [\-A-Za-z]        also does the same (the '\' is unnecessary but harmless)
  371.         ^[^^]            matches any single character that is not a '^' at
  372.                         the beginning of a string
  373.         [\^]            matches a '^'.
  374. The toughest metacharacter to remember is the '^' which has three
  375. meanings: at the beginning of a character class it signals a negated
  376. character class; outside of a character class it matches the beginning of
  377. a string; and when escaped or not the first character in a character class
  378. it matches a literal '^'.
  379.  
  380. Regular expressions are “left greedy”; where there could be more than one
  381. match in a string, a regular expression matches the leftmost one, and
  382. extends the match as far as possible.
  383.  
  384. Now that we’re starting to get the hang of things, more examples using the
  385. replacement functions “sub” and “gsub” mentioned above. The format is
  386. sub(r,s,t) where r is a regular expression, s is the replacement string,
  387. and t is the string in which the search and replace is to be done. The
  388. contents of t before and after the sub are spelled out below.
  389.  
  390. using t = "Don’t run that prune over, runt!":
  391. sub(/run/, "fly", t)    turns t into "Don’t fly that prune over, runt!"
  392. gsub(/run/, "fly", t)    turns t into "Don’t fly that pflye over, flyt!"
  393. gsub(/\brun\b/, "fly", t)    turns t into "Don’t fly that prune over, runt!"
  394. gsub(/run/, "t&k", t)    turns t into "Don’t trunk that ptrunke over, trunkt!"
  395. using t = "#define FOO        1":
  396. sub(/#define\W+(\w+)\W+([0-9]+)/, "int \1 = \2;",t) turns t into
  397.         "int FOO = 1;" (\W+ means one or more non-word characters, \w+
  398.         means one or more word characters, [0-9]+ means one or more digits;
  399.         two groups are tagged).
  400.  
  401. Three programs are supplied to help you do general–purpose listing of
  402. matches or search–and–replace; $MFSLister searches for either plain text
  403. or a regular expression with “Set variables” in the setup dialog, and
  404. lists file name/ line number of all single–line matches to stdout;
  405. $MFS_SuperLister does much the same, but finds matches that span a
  406. variable number of lines; and $MFS_SuperReplace does the ultimate search
  407. and replace, matching either plain text or full–blown regular expressions
  408. over a variable number of lines, handling any number of files at once,
  409. documenting the (post–change) locations of all changes to stdout. Heck, it
  410. even prints the fragments of original text before the changes, so that if
  411. you mess up you can at least (manually) undo the damage.
  412.     */};
  413.  
  414. struct patterns
  415.     {/*
  416.     Summary of patterns
  417. A list of beasts in the pattern zoo (regex stands for regular expression,
  418. pat stands for pattern, str stands for string variable):
  419. Pattern                                        Example
  420. ----------------                -------------------------------
  421. BEGIN                            BEGIN blocks are done before all input
  422. END                                END blocks are done after all input
  423. /regex/                            /Mary( \t)+had/
  424. str ~ /regex/                    (or !~)    $1 ~ /(\-)?[0-9]+/
  425. str ~ "regex"                    (or !~)    $1 ~ "(\\-)?[0-9]+"
  426. relational expression            NF > 4
  427. pattern && pattern                FNR == 1 && /File title:/
  428. pattern || pattern                /Vermont/ || /Maine/
  429. pattern ? pattern : pattern        $3 != 0 ? $2 / $3 > 25 : $2 < 0
  430. ( pattern )                        - see next line
  431. ! pattern                        !($0 == "" || $0 ~/^The end$/) 
  432. pattern1 , pattern2                FNR == 5, FNR == 8
  433.     */};
  434.  
  435. struct operators
  436.     {/*
  437. The operators in hAWK, in order of increasing precedence, are:
  438. -------------------------------------------------------------
  439. =         +=     -=     *=     /=     %=     ^=
  440. Assignment. Both absolute assignment ( var " = " value ) and
  441. operator-assignment (the other forms) are supported. “a += b” is
  442. equivalent to “a = a + b”.
  443.  
  444. ?:            The C conditional expression. This has the form
  445.             expr1 " ? " expr2 " : " expr3
  446. If expr1 is true, the value of the expression is expr2 , otherwise it is
  447. expr3 . Only one of expr2 and expr3 is evaluated.
  448.  
  449. ||            logical OR. In “a || b” if a is true then b is not evaluated.
  450.  
  451. &&            logical AND. In “a && b” if a is false then b is not evaluated.
  452.  
  453. ~ !~        regular expression match, negated match. See “String-matching patterns”.
  454.  
  455. < <= > >= != ==
  456.             the regular relational operators. Note especially that strings
  457.             can be compared, eg if ($3 == "cat"). In “a <= b” or the like,
  458.             if both arguments are numbers the comparison is done
  459.             numerically, otherwise they are compared as ASCII strings.
  460.  
  461. blank        string concatenation;  if a = "John" and b = "Henry" then
  462.             c = a b; produces c = "JohnHenry".
  463.  
  464. +  -        addition and subtraction.
  465.  
  466. * / %        multiplication, division, and modulus (x%y produces the
  467.             remainder of x divided by y, equivalent to x - int(x/y)*y).
  468.  
  469. +  - !        unary plus, unary minus, and logical negation.
  470.  
  471. ^            exponentiation.
  472.  
  473. ++  --    increment and decrement, both prefix and postfix.
  474.  
  475. $            field reference. $0 is the entire current record, $1 the first
  476.             field, and $NF the last field. Fields may be changed or added.
  477.     */};
  478.  
  479. struct numeric /*functions */
  480.     {/*
  481.     Built–in numeric functions
  482. hAWK has the following pre-defined arithmetic functions, with x and y as
  483. arbitrary expressions:
  484. atan2( y , x )        returns the arctangent of y/x in radians.
  485. cos( x )            returns the cosine of x in radians.
  486. exp( x )            the exponential function "e to the x"
  487. int( x )            truncates to integer (eg int(7.325) gives 7); to round,
  488.                     use int(x + .5).
  489. log( x )            the natural logarithm function, base e. For log base 10, use
  490.                     log(x)/log(10).
  491. rand()                returns a random number, 0 <= rand() < 1.
  492. sin( x )            returns the sine of x in radians.
  493. sqrt( x )            the square root function.
  494. srand( x )            use x as a new seed for the random number generator.
  495.                     If no x is provided, the time of day will be used. The
  496.                     return value is the previous seed for the random
  497.                     number generator.
  498.     */};
  499.  
  500. struct string /*functions*/
  501.     {/*
  502.     Built–in string functions
  503. There is only one string operator, the concatenation operator, invoked
  504. when two variables or constants are separated by a space. Other useful
  505. string manuipulations in hAWK are carried out by built–in functions. In
  506. the following table, r is a regular expression, s and t are strings, the a
  507. and b are arrays, and i and n are integers.
  508.  
  509. gsub(r, s, t)        for each substring matching the regular expression r
  510.                     in the string t , substitutes the string s , and
  511.                     returns the number of substitutions. If t is not
  512.                     supplied, uses $0 .
  513. index( s ,  t )        returns the index of the string t in the string s,
  514.                     or 0 if t is not present.
  515. length( s )            returns the length of the string s .
  516. match( s , r )        returns the position in s where the regular expression r
  517.                     occurs, or 0 if r is not present, and sets the values of
  518.                     RSTART and RLENGTH .
  519. split(s, a, r)        splits the string s into the array a on the regular
  520.                     expression r , and returns the number of fields. If r is
  521.                     omitted, FS is used instead.
  522. sprintf( fmt , expr-list )    prints expr-list according to fmt , and returns the
  523.                     resulting string. See the discussion of “printf” for details.
  524. sub(r, s,t)         this is just like gsub , but only the leftmost matching
  525.                     substring is replaced. Returns number of substitutions.
  526. substr(s, i, n)        returns the n-character substring of s starting at i . If n
  527.                     is omitted, the rest of s is used.
  528. tolower( s )        returns a copy of the string s , with all the upper-case
  529.                     characters in s translated to their corresponding
  530.                     lower-case counterparts. Non-alphabetic characters are
  531.                     left unchanged.
  532. toupper( s )        returns a copy of the string s , with all the lower-case
  533.                     characters in s translated to their corresponding
  534.                     upper-case counterparts. Non-alphabetic characters are
  535.                     left unchanged.
  536. lookup ( s )        returns integer–coded C type of s (s should be a word).
  537.                     At present this function is supported only by EnterAct.
  538.                     Types are taken from whatever EnterAct project is open
  539.                     at the time. See “$LookupTest” for an example.
  540.                     Type                            integer returned
  541.                     ----                            ------------
  542.                     defined constant or macro        1
  543.                     file–scope variable                2
  544.                     function                        4
  545.                     enum constant                    8
  546.                     typedef                            16
  547.                     struct tag                        32
  548.                     union tag                        64
  549.                     enum tag                        128
  550.                     other                            0
  551. sort(a,b,s)            produces an index in the array “b” that can be used to
  552.                     access the elements of “a” in sorted order. The string
  553.                     “s” specifies the kind of sort; "a" for ASCII, "n" for
  554.                     numeric, "d" for dictionary order, and "ra", "rn",
  555.                     "rd" for reverse of the same. Returns the number of
  556.                     elements in the array “b”, which is indexed
  557.                     numerically from 1 upwards. The elements of “b” are
  558.                     the indexes of “a” in sorted order provided “b” is
  559.                     accessed in the sequence b[1], b[2], b[3] etc. Typical
  560.                     use is
  561.                         maxIndex = sort(a, b, "d")
  562.                         for (i = 1; i <= maxIndex; ++i)
  563.                             print a[b[i]]
  564.                     which will print the elements of a in sorted
  565.                     dictionary order. See “$WordFrequency” and
  566.                     “$XRef_Full” for examples, and “$SortTest_Nums” for a
  567.                     simple numeric example.
  568. time ( )            returns the current time, eg
  569.                         "Sunday, October 27, 1991 09:03:30 AM" 
  570.                     —note this is the time when the function
  571.                     is called, down to the second, whereas the TIME
  572.                     variable holds the time at which your program run
  573.                     starts, down to the minute. See “$TIME” for an example.
  574. prompt ( s )        displays an OK/Cancel dialog. The string “s” appears
  575.                     at the top of the dialog, and you can type in a string
  576.                     in an edit field. Returns what you type in, as though
  577.                     it was a string constant. Both the string “s” and what
  578.                     you type in are limited to 255 characters. For an
  579.                     example of usage see “$PromptTest” and “$YoungMath”.
  580.                     Typical use is
  581.                         x = prompt("Enter the number of lines to print:")
  582.                         if (x+0 > 0) {
  583.                             while (getline lne > 0 && ++i <= x) print lne }
  584.                     If you cancel the dialog or hit <Return.> without
  585.                     typing in any text, prompt returns the null string "".
  586. progress (s)        displays the string “s” in a dialog on your screen
  587.                     (the message stays on the screen). You can change the
  588.                     message with another “progress” call. “progress”
  589.                     returns the number of times it has been called, and
  590.                     the dialog goes away by itself at the end of your
  591.                     program run. For a test sample, see “$ProgressTest”.
  592. Within the replacement string 's' of gsub(r,s,t) and sub(r,s,t), a '&' is
  593. taken to stand for the entire string of text that was matched by the
  594. regular expression 'r'. For example, gsub(/cat/, "&s", t) with t = "cat
  595. and dogs" produces t = "cats and dogs" after the substitution. Use “\&” if
  596. you want a literal '&' in the replacement string.
  597.  
  598. --and added for hAWK version 2 (mainly file functions):
  599. Note in the functions below where a file or directory name is required it must
  600. be a full pathname, of the form “disk:folder1:folder2:...:folderN:filename”
  601. for a file, or “disk:folder1:...:folderN” or “disk:folder1:..:folderN:”
  602. for a directory (the second version has a colon at the end). For a disk name,
  603. use “disk:” rather than “disk”.
  604. beep( n )        does a SysBeep(n); if the duration "n" is <= 0, the menu bar will
  605.                 flash instead. Durations of 0,1,2,5 work best.
  606. copy( s, t )    copies the file named “s” to the file named “t”. Both file names
  607.                 must be full pathnames (disk:folder:...folder:filename). Either
  608.                 the location or name or both can be changed. If file “t” already
  609.                 exists, it must be closed and unlocked. Both creator and type are
  610.                 preserved, and  the resource fork is copied as well as the data
  611.                 fork. Any kind of file can be copied. To move or rename a file, use 
  612.                     if (copy(s,t)) remove(s)
  613.                 (note this is an efficient way to move a file, but not a very fast
  614.                 way to rename one).
  615.                 Returns 1 if successful, 0 if the copy could not be done.
  616. exists( s )        returns 1 if the file named “s” exists, 0 if it does not. Any kind
  617.                 of file can be tested.
  618. fdate( s )        returns date/time of last modification of file named “s”, format
  619.                     “yr:mo:day:hr:min:sec” where yr is 4 digits, and the rest are 2
  620.                 (eg always 01 rather than just 1). The length of the string is
  621.                 always 19 (or 0 if no date could be extracted) and the colons
  622.                 and digits always occupy the same positions.
  623. fsize( s )        returns size in bytes of the data fork only of the file named “s”
  624. getclip( n )    returns the calling application’s current clipboard text, up to
  625.                 a maximum of the first “n” bytes. Use n = 0 or omit it entirely
  626.                 if you want the entire clipboard. For example, if the current
  627.                 clip is “Some text here” then getclip(6) returns “Some t”
  628.                 whereas getclip(0) or getclip() returns the entire clip. At
  629.                 present this function is supported by: EnterAct.
  630. list( s, a )    given file or directory full pathname in “s”, produces list of
  631.                 full pathnames for all TEXT files in the directory (either the
  632.                 directory named or the directory holding the file), as elements
  633.                 indexed 1,2,3... in the array “a”. Note subdirectories are also
  634.                 excluded. Returns the number of files in the list.
  635. nested( s, a )    given a file full pathname in “s”, generates list of full pathnames
  636.                 for directories at the same level ("sibling folders"); given directory
  637.                 name, generates list of subdirectories at the top level in the named
  638.                 directory (“offspring directories”). The list is returned as elements
  639.                 indexed 1,2,3... in the array “a”. In other words, the same as
  640.                 “list” but for folders rather than TEXT files. Note neither “list”
  641.                 nor “nested” look beneath the top level of the folder in question.
  642.                 Returns the number of directories in the list.
  643. remove( s )        deletes the file named “s”, provided it is closed and unlocked. Use
  644.                 with caution, this is not undoable unless you get lucky using your
  645.                 favourite file recovery tool. Returns 1 if the file was deleted,
  646.                 0 otherwise.
  647. rename( s, t )    takes the file with full pathname “s”, and renames it “t”. The
  648.                 new name “t” can be a full pathname, or just the new file name
  649.                 proper, as in 
  650.                     rename("Disk:dir1:aardvark", "Disk:dir1:fruitbat")
  651.                 or equivalently
  652.                     rename("Disk:dir1:aardvark", "fruitbat")
  653.                 This function works only with files, not directories or volumes,
  654.                 returning 1 if the rename was carried out, 0 if not.
  655.     */};
  656.  
  657. struct control
  658.     {/*
  659. In the following list of control statments, any instance of “statement”
  660. can be replaced by a group of statements enclosed in curly braces {}:
  661.  
  662. { statements }
  663.     Simple grouping of several statements together, so that conditional or
  664.     repeated execution can be applied to the group.
  665. if (condition) statement1 [ else statement1 ]
  666.     If the condition evaluates to true then statement1 is carried out; the
  667.     “else” clause is optional, and its statements will be executed if the
  668.     condition is false.
  669. while (condition) statement 
  670.     The condition is first evaluated, and if it is false then the
  671.     statement is skipped. If it is true then the statement is executed;
  672.     the condition is again evaluated, and the statements again executed if
  673.     the condition is true, and this process continues until the condition
  674.     is false. Note that if the condition is false the first time then the
  675.     statement will not be executed at all. “while” loops are affected by
  676.     break and continue statements.
  677. do statement while (condition)
  678.     The statement is always executed at least once; then the condition is
  679.     evaluated, and if it is true then the statement is excuted again. This
  680.     process continues until the condition is false. Unlike the “while”
  681.     loop, the “do” loop always executes its statement at least once.
  682. for (expr1; expr2; expr3) statement
  683.     eg “for (i = 1; i <= 6; ++i) {print i}”
  684.     Mnemonically, “for it’s (a jolly good fellow)” helps: the “i” stands
  685.     for initialization, the “t” for “test”, and the “s” for “step”. expr1
  686.     is the initialization, executed only once, just before the “for” loop
  687.     proper is entered. Next expr2, the test, is evaluated, and if it is
  688.     true then the statement is executed, otherwise the for loop ends and
  689.     control passes to the next statement beyond it. If the statement is
  690.     executed then expr3, the step, is carried out, and then it’s back to
  691.     the top of the loop —no more initialization, but the sequence test,
  692.     execute, step, continues until the test produces false.
  693. for (var in array) statement
  694.     Indexes for the array are retrieved one–by–one to the variable “var”,
  695.     though not in a readily predictable order, and the statement is
  696.     executed for each index.
  697. break
  698.     For use only among the statements that make up the body of a while,
  699.     do, or for loop. Usually found in the form “if (condition) break;”,
  700.     when the break is executed then control immediately passes to the next
  701.     statement after the loop.
  702. continue
  703.     Also for use only in a while, do, or for loop, and also usually
  704.     executed only when the condition of some if–statement is true. When
  705.     encountered, control passes to the very end of the statements making
  706.     up the body of the loop, and the next iteration of the loop begins.
  707. next    
  708.     Stop processing the current input record. The next input record is
  709.     read and processing starts over with the first pattern in the hAWK
  710.     program. If the end of the input data is reached, the END block(s), if
  711.     any, are executed.
  712. exit [ expression ]
  713.     In an END action, exit truly causes the hAWK program to terminate.
  714.     Anywhere else, the exit statement causes the program to jump to the
  715.     END actions, and only if none are present does the program immediately
  716.     terminate. The “expression” is provided for compatiblilty with
  717.     standard AWK programs, and won’t be of any use to you.
  718.     */};
  719.  
  720. struct function
  721.     {/*
  722. Functions in hAWK take the form:
  723.     "function" name(parameter1, parameter2,...    local1, local2...)
  724.         { 
  725.         statements
  726.          }
  727. They are executed when called from within an action statement.
  728.  
  729. hAWK function definitions begin with the keyword “function”, and no return
  730. type is declared, though a value may optionally be returned. Local
  731. variables are listed after the parameters for the function, more to
  732. simplify the grammar of the language than anything else. Scalar parameters
  733. are passed by value (ie a local copy is made for the function, and the
  734. original variable in the function call is not touched by the function)
  735. whereas array parameters are passed by reference (the parameter array name
  736. refers to the same array that is provided as the argument). Function
  737. definitions must be placed at the top level of your program outside any
  738. pattern–action blocks, and you generally end up with a readable program if
  739. you put all of your function definitions at the end of your program.
  740.  
  741. Here’s a typical function:
  742.         function Swap(a, i, j        temp)
  743.             {
  744.             temp = a[i]
  745.             a[i] = a[j]
  746.             a[j] = temp
  747.             }
  748. When called, it appears for example as
  749.     arr[1] = 7; arr[4] = 9; Swap(arr, 1, 4)
  750. which results in arr[1] = 9, arr[4] = 7. Note that the “temp” variable is
  751. intended for use only within the Swap function, and is a local variable
  752. rather than a parameter of the function.
  753.  
  754. Local variables are initialized to 0/"" each time the function is called.
  755. No space should be put between the function name and the '(' of the
  756. argument list when calling one of your own functions, to avoid invoking
  757. the simple–minded concatenation operator.
  758.  
  759. Functions may return an expression, as in
  760.     function SumArraySquared(a,        sum)
  761.         {
  762.         for (i in a)        #unlike C, array size need not be known separately
  763.             sum += a[i]#note sum is local, automatically inited to zero
  764.         return sum*sum
  765.         }
  766. or
  767.     function StringUpTo(str, upto)
  768.         {
  769.         return substr(str, 1, index(str, upto) - 1)
  770.         }
  771. (eg StringUpTo("This is: a test", ":") would return "This is").
  772.  
  773. Some details about functions:
  774. Newlines are optional after the left curly brace of the function body and
  775. before the closing left brace.
  776. Functions may call each other and may be recursive.
  777. The word func may be used in place of function. For tired typers only.
  778.     */};
  779.  
  780. struct print
  781.     {/*
  782.     The “print” statement
  783. “print” sends simply–formatted strings to a file, stdout by default. The
  784. expressions supplied to the print statement are separated from one another
  785. by commas, and may also be entirely surrounded by parentheses. The
  786. variations are
  787.         print
  788.         print expression1, expression2, ..., expressionN
  789.         print (expression1, expression2, ..., expressionN)
  790. A “print” with no expressions is an abbreviation for
  791.     print$0
  792. Each expression is converted to a string and printed in turn, with each
  793. comma being replaced by the built–in variable OFS, by default a single
  794. blank. Each print statement is terminated with the built–in ORS, by
  795. default a newline.
  796.  
  797. The parenthesized version of “print” is necessary if relational operators
  798. are present in the expressions, since the '>' operator can mean “greater
  799. than” or “redirect output to the file...”—see “Output into files”.
  800.  
  801. The print statement is used in virtually every sample program provided,
  802. and the more–sophisticated “printf” is seldom seen since fancy formatting
  803. is not often needed.
  804.  
  805.     print "" #prints just a blank line
  806.     */};
  807.  
  808. struct printf
  809.     {/*
  810.     The “printf” statement
  811. This function also has a parenthesized and unparenthesized form, 
  812.     printf format, expression1, expression2, ..., expressionN
  813.     printf(format, expression1, expression2, ..., expressionN)
  814. and, as with “print”, the parentheses are needed only if a relational
  815. operator is contained in one of the expressions. The “format” argument is
  816. interpreted as a string, and may contain either literal text to be printed
  817. or format specifications for strings or numbers to be printed. Format
  818. specs are indicated in the format string by a '%', and there should be one
  819. expression following the format for each format specification—eg if you
  820. specify that a string, a number, and a string be printed, then you list
  821. the string, number, and string after the format, in the same order,
  822. separated by commas.
  823.  
  824. The hAWK versions of the printf and sprintf functions accept the following
  825. conversion specification formats, entirely borrowed from C:
  826. %c        an ASCII character. If the argument used for %c is numeric, it is
  827.         treated as a character and printed. Otherwise, the argument is
  828.         assumed to be a string, and the only first character of that
  829.         string is printed.
  830. %d        a decimal number (the integer part).
  831. %i        just like %d .
  832. %e        a floating point number of the form [-]d.ddddddE[+-]dd .
  833. %f        a floating point number of the form [-]ddd.dddddd .
  834. %g        use e or f conversion, whichever is shorter, with nonsignificant zeros
  835.             suppressed.
  836. %o        an unsigned octal number (again, an integer).
  837. %s        a character string.
  838. %x        an unsigned hexadecimal number (an integer).
  839. %X        like %x , but using ABCDEF instead of abcdef .
  840. %%         a single % character; no argument is converted.
  841.  
  842. There are optional, additional parameters that may lie between the % and
  843. the control letter (also from C):
  844. -                the expression should be left justified within its field
  845.                 (note if the '-' is absent then the expression is right
  846.                 justified)
  847. width            the field should be padded to this width. If the number
  848.                 has a leading zero, then the field will be padded with
  849.                 zeros. Otherwise it is padded with blanks.
  850. . prec            a number indicating the maximum width of strings or digits
  851.                 to the right of the decimal point.
  852. For example, %-23.14s prints strings in a field 23 characters wide, left
  853. justified, printing at most 14 characters from the string. And %8.4f will
  854. print a floating point number in a field 8 characters wide, right
  855. justified, with 4 digits to the right of the decimal point.
  856.  
  857. The dynamic width and prec capabilities of the C library printf routines
  858. are not supported. However, they may be simulated by using the hAWK
  859. concatenation operation to build up a format specification dynamically.
  860.  
  861. Some examples:
  862. “print var” always appends the value of ORS (by default a newline);
  863. to avoid this, use
  864.     printf("%s ", var)
  865. and when a newline is needed, supply one yourself with something like
  866.     print ""        or         printf("%s\n", var).
  867.  
  868. Given strings of variable width in fields $1 and $2, reformat to print
  869. these strings right–justified in two nicely–lined–up columns:
  870.         {    one[++n] = $1
  871.             two[n] = $2
  872.             if (w1 < length($1))
  873.                 w1 = length($1)
  874.             if (w2 < length($2))
  875.                 w2 = length($2)
  876.  
  877.         }
  878.     END    {w1 += 2; w2 += 2;#a couple of spaces between columns
  879.             for (i = 1; i <= n; ++i)
  880.                 printf "%" w1 "s" "%" w2 "s\n", one[i], two[i]
  881.             }
  882. —this illustrates using the hAWK concatenation operation “to build up a
  883. format specification dynamically”; for example, if w1 = 9 and w2 = 15
  884. (after adding 2) then we get
  885.         printf "%9s%15s\n", one[i], two[i]
  886. as the effective printf statement.
  887.     */};
  888.  
  889. struct redirect
  890.     {/*
  891. OUTPUT:
  892. By default, “print” and “printf” send all of their output to stdout.
  893. However, the redirection operators '>' and '>>' allow you to send output
  894. to any text file. Redirecting output takes one of the forms
  895.     print expression–list > outfile
  896.     print(expression–list) > outfile
  897.     printf format, expression–list > outfile
  898.     printf(format, expression–list) > outfile
  899.     print > outfile
  900. or any of those with '>>' instead of '>'. The '>' operator will erase the
  901. contents of outfile before beginning to write to it, whereas '>>' will
  902. append what is being printed to outfile without clearing the file first.
  903. Both operators open the file “outfile” the first time it is encountered in
  904. the program, and keep it open. The file will be closed for you at the end
  905. of your program, but if you have many files to write to you should close
  906. each output file yourself when you are done with it, with
  907. “close(outfile)”.
  908.  
  909. INPUT:
  910. “getline” is a built–in function that allows you to retrieve input records
  911. from the current input file or from any other file. As you know, the
  912. default behaviour of a hAWK program is to retrieve input from your input
  913. files one record at a time, marching through the records and files from
  914. beginning to end. Often, however, one needs to read in a group of lines
  915. until some condition is met, or interrupt regular input to retrieve
  916. records from some other file, and these are the special capabilities that
  917. “getline” provides. It can be used in the following ways:
  918.     getline                    sets $0 from next input record; sets NF, NR, FNR .
  919.     getline < file            sets $0 from next record of file; sets NF .
  920.     getline var             sets var from next input record; sets NR, FNR .
  921.     getline var < file        sets var from next record of file .
  922. and in all cases “getline” returns 1 if a record was successfully
  923. retrieved, 0 if the end of file was encountered, and -1 if some problem
  924. occurred, such as failure to find the file.
  925.  
  926. The effect of “getline” by itself is to dump the current string in $0 and
  927. replace it with the next input record, setting all the usual built–in
  928. variables. Program execution then continues with the statement following
  929. “getline”. By comparison, the “next” statement does everything that
  930. “getline” by itself does, but in addition processing starts over with the
  931. first pattern in your hAWK program.
  932.  
  933. If a variable name is present immediately after “getline”, then the input
  934. record is retrieved to the variable instead of to $0. The '<' symbol is
  935. the input redirection operator meaning “get input from the file...”, and
  936. is followed by the name of the input file to use. Note that file names
  937. must be full path names, as is always the case in hAWK.
  938.     */};
  939.  
  940.